/*-------------------------------------------------------------------------
 - Copyright (c) 2024-2025 [XD-AMCC TEAM]
 - [XD-AMCC] is licensed under Mulan PSL v2.
 - You can use this software according to the terms and conditions of the Mulan PSL v2.
 - You may obtain a copy of Mulan PSL v2 at:
 -          http://license.coscl.org.cn/MulanPSL2
 - THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
 - OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 - TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 - See the Mulan PSL v2 for more details.
 ------------------------------------------------------------------------*/

/**
 * @brief Internal interface for class backpatcher.
 *
 * @author  WXQ#XDU
 * @date    2025.01
 */

#pragma once

#ifndef AMCC__BACKPATCHER_H
#define AMCC__BACKPATCHER_H

#include "../../include/amcc_list.h"

#include "codemgr.h"

AMCC_DECL_BEGIN


// The function of class backpatcher is TOO simple,
// so in second revision, class backpatcher is reduced to a simple submodule:
//    - with only a few functions as below,
//    - without any inner data.
typedef struct  backpatcher {

} t_backpatcher, * t_backpatcher_ptr;


#define CHAIN_TC   ".tc"
#define CHAIN_FC   ".fc"
#define CHAIN_NC   ".nc"


/**
 * @brief Create a new chain for an incomplete goto instruction.
 *
 * If pGotoCode is null, then return a new chain with zero element.
 *
 * @param pGotoCode  pointer to an incomplete goto instruction
 * @param chainName  tip for chain name
 * @return pointer to the chain holding the goto instruction.
 */
extern t_list_ptr emitter_makeChain(t_ircode_ptr pGotoCode,
                                    const char * chainName);

/**
 * @brief   Add a goto instruction into the target chain.
 *
 * If targetChain is NULL, then a new chain is created,
 * this new chain is used as targetChain and return to caller.
 *
 * @param targetChain   pointer to the target chain
 * @param pGotoCode pointer to an incomplete goto instruction
 * @param chainName tip for chain name
 * @return Return the target chain.
 */
extern t_list_ptr emitter_add2Chain ( t_list_ptr targetChain,
                                t_ircode_ptr pGotoCode,
                                const char * chainName);
/**
 * @brief Merge two chains into a resulting chain.
 *
 * This function copy all elements in chain1 and chain2 into
 * the chainReturn.
 *
 * If chainReturn is NULL, then a new chain is created,
 * this new chain is used as chainReturn and return to caller.
 *
 * This function does not modify chain1 and chain2.
 *
 * @param chain1  pointer to the 1st chain
 * @param chainName1 tip for name of chain1
 * @param chain2  pointer to the 2nd chain
 * @param chainName2 tip for name of chain2
 * @param chainReturn  pointer to the result chain
 * @param chainNameReturn tip for name of result chain
 * @return return the chainReturn.
 */
extern t_list_ptr emitter_mergeChain(t_list_ptr chain1, const char * chainName1,
                                     t_list_ptr chain2, const char * chainName2,
                          t_list_ptr chainReturn, const char * chainNameReturn);

/**
 * @brief Perform back-patch.
 *
 * This function fills id of target-code into all incomplete
 * goto instruction in the chain.
 *
 * This function does not modify the chain.
 *
 * @param chain       pointer to the chain
 * @param targetCode  target ir-code for incomplete jumping
 * @param chainName   tip for chain name
 */
extern void emitter_backpatch(t_list_ptr chain, t_ircode_id targetCode,
                              const char * chainName);

// Let dest = src , and log action
#define ASSIGN_CHAIN(dest, destName, src, srcName)      \
    do{ dest = src;                                     \
        log_trace(  "    assignChain: %s = %s (%tx)",   \
        destName, srcName, src);                        \
    } while(0)



/**
 * @brief  Get the target ir-code defined by a label of source program.
 *
 * The id of target ir-code is set by emitter_setTargetOfLabel().
 *
 * @param pThis      pointer to this emitter
 * @param labelNode  parse-tree node holding the label name
 *
 * @return Return the target ir-code id defined by label.
 *   Return 0 if emitter has not seen the definition of label.
 */
extern t_ircode_id emitter_getTargetOfLabel(t_emitter_ptr pThis,
                                            t_tree_ptr labelNode);

/**
 * @brief  Set the target ir-code defined by a label of source program.
 *
 * This function is called when emitter sees a label definition.
 *
 * If there are any forward references to the specified label,
 * backpatch will be performed for this label in this function.
 *
 * @note This function is the action for production "LAB->id:"
 *       in section 4.9.1 of our textbook.
 *
 * @param pThis      pointer to this emitter
 * @param labelNode  parse-tree node holding the label name
 * @param targetCode target ir-code marked by label
 */
extern void emitter_setTargetOfLabel(t_emitter_ptr pThis,
                                     t_tree_ptr labelNode,
                                     t_ircode_id targetCode);

/**
 * @brief Make chain for a forward-referenced label of source program.
 *
 * This function is called when emitter sees a forward reference to
 * the specified label.
 *
 * @note This function is a part of action for production "goto id"
 *       in the section 4.9.1 of our textbook.
 *
 * @note In AMCC, these chains are recorded in emitter.functionStack,
 *   but in textbook, they are recorded in the symbol table entry of a label.
 *
 * @param pThis      pointer to this emitter
 * @param labelNode  parse-tree node holding the label name
 * @param pGotoCode  pointer to an incomplete goto instruction
 *
 * @return pointer to the chain.
 */
extern t_list_ptr emitter_makeChainOfLabel(t_emitter_ptr pThis,
                                           t_tree_ptr labelNode,
                                           t_ircode_ptr  pGotoCode);


AMCC_DECL_END

#endif //AMCC__BACKPATCHER_H
